# -*- coding: utf-8 -*-
import scrapy

import json
import logging
from copy import copy, deepcopy
from urllib.parse import urljoin
from FDC_spider.items import FdcEstateGuidItem, FdcBuildingItem, FdcRoomItem

logger = logging.getLogger(__name__)


class HuanggangSpider(scrapy.Spider):
    name = 'huanggang'
    allowed_domains = ['hgfdcscxx.com']
    start_urls = ['http://www.hgfdcscxx.com/Aspx/Project/List']
    project_detail_url = 'http://www.hgfdcscxx.com/Aspx/Project/Info?method=project_info_table'  # POST 项目详情url
    permit_li_url = 'http://www.hgfdcscxx.com/Aspx/Project/Info?method=ysz_list'  # POST 预售许可证列表url
    permit_url = 'http://www.hgfdcscxx.com/Aspx/Project/Info?method=ysz_table'  # POST 预售许可证信息url
    building_li_url = 'http://www.hgfdcscxx.com/Aspx/Project/Info?method=xkb_list'  # POST 楼栋列表url
    room_li_url = 'http://www.hgfdcscxx.com/Aspx/Project/Info?method=build_table'  # POST 房号列表url
    room_detail_url = 'http://www.hgfdcscxx.com/Aspx/Project/RoomInfo?method=room_info_table'  # POST 房号详情url

    def parse(self, response):
        """
        获取项目列表
        :param response:
        :return:
        """
        try:
            page_num = copy(response.meta['page_num'])
        except:
            page_num = 1
        # 获取当前页项目列表
        tr_li = response.xpath("//table[@id='GridView1']//tr[position()>1]")  # 首行为表头
        if tr_li:
            for tr in tr_li:
                item_eg = FdcEstateGuidItem()
                item_eg['projectName'] = tr.xpath("./td[2]/a/text()").extract_first()
                item_eg['projectUrl'] = urljoin(response.request.url, tr.xpath("./td[2]/a/@href").extract_first())
                item_eg['projectAddress'] = tr.xpath("./td[3]/text()").extract_first()
                item_eg['developerName'] = tr.xpath("./td[4]/text()").extract_first()
                item_eg['projectId'] = self._get_project_code(item_eg['projectUrl'])
                if item_eg['projectId']:
                    # 获取项目详情
                    headers = {
                        'Referer': item_eg['projectUrl'],
                    }
                    data = {
                        'code': item_eg['projectId'],
                    }
                    yield scrapy.FormRequest(
                        self.project_detail_url,
                        headers=headers,
                        formdata=data,
                        callback=self.parse_project_detail,
                        meta=dict(item_eg=deepcopy(item_eg), ),
                        priority=7,
                    )
                else:
                    logger.error(
                        '第{}页 {}-{} 项目code提取出错'.format(page_num, item_eg['projectName'], item_eg['projectUrl']))
        else:
            logger.error('第{}页 项目列表获取为空'.format(page_num))

        # 翻页
        try:
            total_page = int(response.xpath("//span[@id='PagerControl_lblTotalPageCount']/text()").extract_first())
        except:
            total_page = 11  # 设置一个初始值，在提取出错时不影响翻页
            logger.error('第{}页 总页数提取出错'.format(page_num))
        if page_num < total_page:
            page_num += 1
            # 构造翻页 POST 请求
            view_state = response.xpath("//input[@id='__VIEWSTATE']/@value").extract_first()
            view_stategenerator = response.xpath("//input[@id='__VIEWSTATEGENERATOR']/@value").extract_first()
            event_validation = response.xpath("//input[@id='__EVENTVALIDATION']/@value").extract_first()
            data = {
                '__EVENTTARGET': 'PagerControl$btnGo',
                '__EVENTARGUMENT': '',
                '__LASTFOCUS': '',
                '__VIEWSTATE': view_state,
                '__VIEWSTATEGENERATOR': view_stategenerator,
                '__EVENTVALIDATION': event_validation,
                'searchType': 'title',
                'txtKeywords': '',
                'txtProjName': '',
                'txtProjAddr': '',
                'txtCompany': '',
                'PagerControl$txtNewPageIndex': str(page_num),
                'PagerControl$ddlPageSize': '20',
            }
            yield scrapy.FormRequest(
                self.start_urls[0],
                formdata=data,
                meta=dict(page_num=deepcopy(page_num), ),
                priority=10,
            )

    def parse_project_detail(self, response):
        """
        获取项目详情
        :param response:
        :return:
        """
        item_eg = copy(response.meta['item_eg'])
        try:
            resp = json.loads(response.body.decode())
            resp_m = resp['m']
            assert resp and resp_m
        except:
            logger.error('{}-{} 项目详情获取失败'.format(item_eg['projectName'], item_eg['projectId'], ))
        else:
            item_eg['districtName'] = resp_m.get('DNAME', None)
            item_eg['floorAreaRatio'] = resp_m.get('RJL', None)
            item_eg['salesTel'] = resp_m.get('SLDH', None)
            item_eg['projectBrief'] = resp_m.get('XMJL', None)
            item_eg['totalArea'] = resp_m.get('GHZJZMJ', None)
            item_eg['totalResidenceArea'] = resp_m.get('ZZJZMJ', None)
            item_eg['totalNonResidenceArea'] = resp_m.get('FZZJZMJ', None)
            item_eg['commencementDate'] = resp.get('KSRQ', None)
            item_eg['completionDate'] = resp.get('WGRQ', None)
            item_eg['totalSoldRoomNum'] = resp.get('ALL_TOTAL_COUNT', None)
            item_eg['totalSoldArea'] = resp.get('ALL_TOTAL_AREA', None)
            item_eg['qualificationGrade'] = resp.get('ZZDJ', None)
            item_eg['qualificationCertificateNo'] = resp.get('ZZZSBH', None)
            headers = {
                'Referer': item_eg['projectUrl'],
            }
            data = {
                'code': item_eg['projectId'],
            }

            # 获取预售许可证列表
            yield scrapy.FormRequest(
                self.permit_li_url,
                headers=headers,
                formdata=data,
                callback=self.parse_permit_li,
                meta=dict(item_eg=deepcopy(item_eg), ),
                priority=9,
            )

            # 获取预售许可证下的楼栋列表
            yield scrapy.FormRequest(
                self.building_li_url,
                headers=headers,
                formdata=data,
                callback=self.parse_building_li,
                meta=dict(item_eg=deepcopy(item_eg), ),
                priority=8,
            )

    def parse_permit_li(self, response):
        """
        获取预售许可证列表
        :param response:
        :return:
        """
        item_eg = copy(response.meta['item_eg'])
        try:
            resp = json.loads(response.body.decode())
            is_show = resp.get('isshow', False)
            permit_li = resp.get('list', list())
            assert is_show and permit_li
        except:
            logger.warning('{}-{} 预售许可证列表获取为空'.format(item_eg['projectUrl'], item_eg['projectName'], ))
        else:
            for permit_dict in permit_li:
                item_eg['preSalePermit'] = permit_dict.get('XKZH', None)
                item_eg['permitId'] = permit_dict.get('CODE', None)
                if item_eg['permitId']:
                    # 获取许可证详情
                    headers = {
                        'Referer': item_eg['projectUrl'],
                    }
                    data = {
                        'code': item_eg['permitId'],
                    }
                    yield scrapy.FormRequest(
                        self.permit_url,
                        headers=headers,
                        formdata=data,
                        callback=self.parse_primit,
                        meta=dict(item_eg=deepcopy(item_eg), ),
                        priority=10,
                    )
                else:
                    logger.error('{}-{}-{} 预售许可证code提取出错'.format(item_eg['projectName'], item_eg['projectId'],
                                                                 item_eg['preSalePermit'], ))

    def parse_primit(self, response):
        """
        获取许可证信息
        :param response:
        :return:
        """
        item_eg = copy(response.meta['item_eg'])
        try:
            resp = json.loads(response.body.decode())
            resp_m = resp.get('m', None)
            assert resp and resp_m
        except:
            logger.error('{}-{}-{}-{} 预售许可证信息获取出错'.format(item_eg['projectName'], item_eg['projectId'],
                                                          item_eg['preSalePermit'], item_eg['permitId'], ))
        else:
            item_eg['permitResidenceNum'] = resp.get('zz_count', None)
            item_eg['permitResidenceArea'] = resp.get('zz_area', None)
            item_eg['permitCommerceNum'] = resp.get('sy_count', None)
            item_eg['permitCommerceArea'] = resp.get('sy_area', None)
            item_eg['permitOtherNum'] = resp.get('qt_count', None)
            item_eg['permitOtherArea'] = resp.get('qt_area', None)
            item_eg['certDate'] = resp_m.get('FZRQ', None)
            item_eg['preSaleDepositBank'] = resp_m.get('YSZJKHYH', None)
            item_eg['preSaleAccountNum'] = resp_m.get('YSZJZH', None)
            yield item_eg

    def parse_building_li(self, response):
        """
        获取楼栋列表
        :param response:
        :return:
        """
        item_eg = copy(response.meta['item_eg'])
        try:
            resp = json.loads(response.body.decode())
            permit_bd_list = resp.get('xkzh_list', None)
            assert permit_bd_list
        except:
            logger.error('{}-{} 预售许可证-楼栋列表获取出错'.format(item_eg['projectUrl'], item_eg['projectName']))
        else:
            for permit_bd_dict in permit_bd_list:
                permit = permit_bd_dict.get('XKZH', None)
                bd_li = permit_bd_dict.get('LIST', None)
                if bd_li:
                    for bd_dict in bd_li:
                        item_bd = FdcBuildingItem()
                        item_bd['projectName'] = item_eg['projectName']
                        item_bd['districtName'] = item_eg['districtName']
                        item_bd['projectId'] = item_eg['projectId']
                        item_bd['preSalePermit'] = permit
                        item_bd['blockName'] = bd_dict.get('BUILDNAME', None)
                        try:
                            item_bd['buildingId'] = bd_dict.get('BUILDCODE', None)
                            assert item_bd['buildingId']
                        except:
                            logger.error(
                                '{}-{}-{}-{} 楼栋id获取为空'.format(item_eg['projectUrl'], item_bd['projectName'], permit,
                                                              item_bd['blockName']))
                        else:
                            yield item_bd

                            # 获取当前楼栋的房号列表
                            headers = {
                                'Referer': item_eg['projectUrl'],
                            }
                            data = {
                                'houseUse': '所有',
                                'houseType': '所有',
                                'houseState': '所有',
                                'houseBuildArea': ',',
                                'houseInsideArea': ',',
                                'buildcode': item_bd['buildingId'],
                            }
                            yield scrapy.FormRequest(
                                self.room_li_url,
                                headers=headers,
                                formdata=data,
                                callback=self.parse_room_li,
                                meta=dict(item_bd=deepcopy(item_bd), ),
                                priority=9,
                            )
                else:
                    logger.error('{}-{}-{} 楼栋列表提取为空'.format(item_eg['projectUrl'], item_eg['projectName'], permit))

    def parse_room_li(self, response):
        """
        获取房号列表
        :param response:
        :return:
        """
        item_bd = copy(response.meta['item_bd'])
        try:
            resp = json.loads(response.body.decode())
            room_li = resp.get('list', None)
            assert room_li
        except:
            logger.error(
                '{}-{}-{}-{} 房号列表获取出错'.format(item_bd['projectName'], item_bd['projectId'], item_bd['preSalePermit'],
                                              item_bd['blockName']))
        else:
            for room_dict in room_li:
                item_rm = FdcRoomItem()
                item_rm['projectName'] = item_bd['projectName']
                item_rm['blockName'] = item_bd['blockName']
                item_rm['buildingId'] = item_bd['buildingId']
                item_rm['roomNo'] = room_dict.get('RoomNo', None)
                item_rm['roomId'] = room_dict.get('Code', None)
                item_rm['unitName'] = room_dict.get('UnitName', None)
                item_rm['roomUse'] = room_dict.get('Ghyt', None)
                item_rm['roomStructure'] = room_dict.get('Fwhx', None)
                item_rm['roomArea'] = room_dict.get('Ycjzmj', None)
                item_rm['innerArea'] = room_dict.get('Yctnmj', None)
                item_rm['saleStatus'] = room_dict.get('State', None)
                item_rm['roomFloor'] = room_dict.get('FloorIndex', None)

                # 获取房号详情
                if item_rm['roomId']:
                    headers = {
                        'Referer': 'http://www.hgfdcscxx.com/Aspx/Project/RoomInfo?code={}'.format(item_rm['roomId']),
                    }
                    data = {
                        'code': item_rm['roomId'],
                    }
                    yield scrapy.FormRequest(
                        self.room_detail_url,
                        headers=headers,
                        formdata=data,
                        callback=self.parse_room_detail,
                        meta=dict(item_rm=deepcopy(item_rm), ),
                        priority=10,
                    )
                else:
                    logger.error('{}-{}-{}-{}-{} 房号id提取为空'.format(item_bd['projectName'], item_bd['projectId'],
                                                                  item_bd['preSalePermit'],
                                                                  item_bd['blockName'], item_rm['roomNo']))

    def parse_room_detail(self, response):
        """
        获取房号详情
        :param response:
        :return:
        """
        item_rm = copy(response.meta['item_rm'])
        try:
            resp = json.loads(response.body.decode())
            resp_m = resp.get('m', None)
            assert resp, resp_m
        except:
            logger.error(
                '{}-{}-{}-{} 房号详情获取出错'.format(item_rm['projectName'], item_rm['projectId'], item_rm['blockName'],
                                              item_rm['roomNo']))
        else:
            item_rm['isMortgage'] = resp.get('dy', None)
            item_rm['isSealedOff'] = resp.get('cf', None)
            item_rm['verandaType'] = resp_m.get('ytlx', None)
            item_rm['roomLocation'] = resp_m.get('fwzl', None)
            item_rm['roomNature'] = resp_m.get('fwxz', None)
            item_rm['forecastBuildArea'] = resp_m.get('ycjzmj', None)
            item_rm['forecastInnerArea'] = resp_m.get('yctnmj', None)
            item_rm['forecastSharedArea'] = resp_m.get('ycftmj', None)
            yield item_rm

    @staticmethod
    def _get_project_code(_str: str or None) -> str or None:
        """
        提取项目code
        :param _str:
        :return:
        """
        try:
            ret = _str.split('=')[1]
        except:
            return
        else:
            return ret
